/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Eng_Ahmed Salama
 */
/* Imports the java packages. */
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
import java.io.*;
import java.net.*;
/*
Class CClient - Implements the methods declared or called in the chat application client. This _
file connects the chat client to chat server.
   Method:
      - addMessager()
      - getBroadCastSender()
      - getPrivateSender()
      - connect()
      - runClient()
      - run()
      - sendBroadMsg()
      - sendListMsg()
      - sendPrivateMessage()

*/
public class CClient extends Thread
{
   /* Declares the objects and initializes the variables. */
   private String userId="";
   private String pwd="";
   ByteBuffer buffer=ByteBuffer.allocateDirect(1024);
   SocketChannel Psc=null;
   SocketChannel Asc=null;
   private InetSocketAddress AAddr=null;
   private InetSocketAddress PAddr=null;
   private int APort=9999;
   private int PPort=8888;
   boolean connectStatus=false;
   private ArrayList Lmsg=null;
   private boolean Validity_Checker=false;
   public Messager usrlist=null;
   public Messager bcmsg=null;
   public Messager prmsg=null;
   boolean chkfirst=true;
   /* Defines the default constructor. */
   public CClient()
   {
   }
   /* Implements the addMessager() method. */
   public void addMessager(Messager usrlist, Messager bcmsg, Messager prmsg)
   {
      this.usrlist=usrlist;
      this.bcmsg=bcmsg;
      this.prmsg=prmsg;
   }
   /*Implements the connect() method. This method connects the specified user to the server.*/
   public void connect(String UserId,String Password,String HostAddress) throws
   NotYetConnectedException
   {
      this.userId=UserId;
      this.pwd=Password;
      try
      {
      Asc=SocketChannel.open(new InetSocketAddress(HostAddress,APort));
      Psc=SocketChannel.open(new InetSocketAddress(HostAddress,PPort));
      while(!Asc.finishConnect())
      {
      }
      while(!Psc.finishConnect())
      {
      }
      runClient();
      sendBroadMsg("");
      sendPrivateMessage(" "," ");
      }
      catch(Exception e1)
      {
         throw new NotYetConnectedException();
      }
   }
/* Implements the runClient() method. This method runs the client. */
   public void runClient() throws Exception
   {
      this.start();
      new PrivateReceiver(Psc);
   }
/*Implements the run() method. This method is invoked when thread is started.*/
public void run()
   {
      byte[] Tdata=null;
      while(true)
      {
         try
         {
            buffer.clear();
            int nbyte=Asc.read(buffer);
            if(nbyte==-1)
            {
               bcmsg.message("Connection Closed");
               Asc.close();
               return;
            }
            if (nbyte>0)
            {
/*Reads the messages from the chat server.*/
buffer.flip();
Tdata=new byte[nbyte];
buffer.get(Tdata,0,nbyte);
if(Tdata[0]!=31)
               {
                  String s=new String(Tdata);
                  bcmsg.message(s);
               }
               else
               {
                  String s=new String(Tdata);
                  usrlist.message(s);
               }
            }
         }
         catch(IOException ex)
         {
            try
            {
               Asc.close();
            }
            catch(IOException ec)
            {
               ec.printStackTrace();
            }
         }
      }
   }
/*Implements the sendBroadMsg() method. This method broadcast the message to all the end users.*/
   public void sendBroadMsg(String msg)
   {
      try
      {
         if(!connectStatus)
         {
            String tmps=userId+(char)28+pwd+(char)29+"";
            ByteBuffer b=ByteBuffer.wrap(tmps.getBytes());
            Asc.write(b);
            connectStatus=true;
         }
         else
         {
            ByteBuffer b=ByteBuffer.wrap(msg.getBytes());
            Asc.write(b);
         }
      }
      catch(Exception sb)
      {
         sb.printStackTrace();
      }
   }
/*Implements the sendListMsg() method. This method sends the user list to the end user.*/
public void sendListMsg(String msg)
   {
      try
      {
         String tmps=""+(char)31+"";
         ByteBuffer b=ByteBuffer.wrap(tmps.getBytes());
         Asc.write(b);
      }
      catch(Exception sl)
      {
         sl.printStackTrace();
      }
   }
/*Implements the sendPrivateMessage() method.*/
public void sendPrivateMessage(String Msg,String to)
   {
      try
      {
         String Ts=null;
         if(chkfirst)
         {
            Ts=to+(char)3+userId+(char)3+Msg;
            chkfirst=false;
         }
         else
            Ts=to+(char)3+Msg;
            ByteBuffer b=ByteBuffer.wrap(Ts.getBytes());
            Psc.write(b);
      }
      catch(Exception se)
      {
         se.printStackTrace();
      }
   }
   /*Creates the PrivateReceiver class.*/
   class PrivateReceiver extends Thread
   {
      SocketChannel P_channel=null;
      ByteBuffer buff=ByteBuffer.allocateDirect(1024);
      byte[] Tdata=null;
      /*Defines the default constructor.*/
      PrivateReceiver(SocketChannel chan )
      {
          this.P_channel=chan;
         start();
      }
      /*Implements the run() method.*/
      public void run()
      {
         while(true)
         {
            try
            {
               buff.clear();
               int nbyte=P_channel.read(buff);
               if(nbyte==-1)
               {
                  prmsg.message("Connection Closed");
                  P_channel.close();
                  return;
               }
               if (nbyte>0)
               {
                  /* Reads the data. */
                  buff.flip();
                  Tdata=new byte[nbyte];
                  buff.get(Tdata,0,nbyte);
                  String s=new String(Tdata);
                  prmsg.message(s);
               }
            }
            catch(IOException ex)
            {
               try
               {
               P_channel.close();
               }
               catch(IOException ec)
               {
                  ec.printStackTrace();
               }
            }
         }
       }
   };
}
